#include  "Typedef.h"
#include  "macros.h"

#include  "hal_mcu.h"
#include  "hal_uart.h"

#include  "CC2500.h"
#include  "CC1100.h"
#include  "Timer.h"

#include  "GlobalMethod.h"

#include  "Phy_Frame.h"
#include  "Wirelessprotocol.h"
#include  "WirelessComm.h"

#include  "eSeal_Management.h"


#define  WIRELESS_COMM_OVERTIME                             (300)
#define  WIRELESS_COMM_RETRY_TIMES                          (3)

#define  WIRELESS_COMM_FLASH_TIME                           (60000)

#define  WIRELESS_COMM_LF_WAKE_UP_DELAY                     (100)

#define  WIRELESS_COMM_STATUS_IDLE                          (0x01)
#define  WIRELESS_COMM_STATUS_LF_TRANS                      (0x02)
#define  WIRELESS_COMM_STATUS_UHF_TRANS                     (0x03)
#define  WIRELESS_COMM_STATUS_UHF_RECVING                   (0x04)
#define  WIRELESS_COMM_STATUS_UHF_RECV_OVERTIME             (0x05)
#define  WIRELESS_COMM_STATUS_UHF_RECV_SUCCESS              (0x06)
#define  WIRELESS_COMM_STATUS_UHF_RECV_ERR                  (0x07)


READER_PROPERTY  ReaderProperty;

PHY_RX_FRAME  RecvPacket;
WIRELESSPROTOCOL_P2P_UP_FRAME  RecvFrame;
WIRELESS_COMM_CONTROL   WirelessControlWord;
INT8U  WirelessLink_Timer;



void  WirelessCommInit(void)
{
    INT8U err;
    WirelessControlWord.WirelessCommStatus = WIRELESS_COMM_STATUS_IDLE;
    WirelessControlWord.RecvOverTimerID = Timer_Apply(WIRELESS_COMM_OVERTIME,&err);
    WirelessControlWord.RetryCnt = 0;
    WirelessControlWord.PreviousSentCmd = WIRELESSPROTOCOL_CMD_NULL;
    WirelessControlWord.bUHFCommEstablished = FALSE;
    
    WirelessComm_TimerInit();
}

void   WirelessCommReset(void)
{
    WirelessControlWord.WirelessCommStatus = WIRELESS_COMM_STATUS_IDLE;
    WirelessControlWord.RetryCnt = 0;
    WirelessControlWord.PreviousSentCmd = WIRELESSPROTOCOL_CMD_NULL;
    WirelessControlWord.bUHFCommEstablished = FALSE;
}

void  WirelessComm_TimerUpdate(void)
{
    StopTimer(WirelessLink_Timer);
    StartTimer(WirelessLink_Timer);
}

void  WirelessComm_TimerInit(void)
{
    INT8U err;
    WirelessLink_Timer = Timer_Apply(WIRELESS_COMM_FLASH_TIME , &err);
    
}

void  WirelessComm_TimerStart(void)
{
    StopTimer(WirelessLink_Timer);
    StartTimer(WirelessLink_Timer);
}

void  WirelessComm_TimerLoop(void)
{
    ESEAL_DETAIL *peSeal;

    if(isTimeOver(WirelessLink_Timer))
    {
      WirelessCommReset();
      peSeal = eSeal_Get_eSealObj();
      if (peSeal)
      {
          eSeal_Del_eSealObj(peSeal); 
      }
      StopTimer(WirelessLink_Timer);
      //StartTimer(WirelessLink_Timer);
    }
}

INT8U  WirelessCommLFWakeUp(void)
{
    INT8U err;
    INT8U RxErr;
    err = WIRELESS_COMM_LF_WAKE_UP_FAILED;
    WirelessControlWord.PreviousSentCmd = WIRELESSPROTOCOL_CMD_NULL;
    WirelessControlWord.RetryCnt = 0;
    WirelessControlWord.WirelessCommStatus = WIRELESS_COMM_STATUS_LF_TRANS;
    WirelessControlWord.bUHFCommEstablished = FALSE; 
    do 
    {
        switch (WirelessControlWord.WirelessCommStatus)
        {
        case WIRELESS_COMM_STATUS_IDLE:
            break;
        case WIRELESS_COMM_STATUS_LF_TRANS:
          
            eSeal_SendCmd_LowFrequencyWakeUp(ReaderProperty.UHF_CommChannel , &err);
            WirelessControlWord.PreviousSentCmd = WIRELESSPROTOCOL_CMD_LF_WAKEUP;
            StartTimer(WirelessControlWord.RecvOverTimerID);
            WirelessControlWord.WirelessCommStatus = WIRELESS_COMM_STATUS_UHF_TRANS;
            
            break;
        case WIRELESS_COMM_STATUS_UHF_TRANS:
            DELAY_MS(WIRELESS_COMM_LF_WAKE_UP_DELAY);
            eSeal_SendCmd_Collect(CMD_COLLECT_RULE_ALL,&err);
            WirelessControlWord.PreviousSentCmd = WIRELESSPROTOCOL_BROADCAST_CMD_COLLECT;
            WirelessControlWord.WirelessCommStatus = WIRELESS_COMM_STATUS_UHF_RECVING;
            
            break;
        case WIRELESS_COMM_STATUS_UHF_RECVING:
            if (isTimeOver(WirelessControlWord.RecvOverTimerID))
            {
                StopTimer(WirelessControlWord.RecvOverTimerID);
                WirelessControlWord.RetryCnt++ ;
                WirelessControlWord.WirelessCommStatus = WIRELESS_COMM_STATUS_LF_TRANS;
                break;
            }
            RxErr = CC2500_rxRecvPacket(RecvPacket.PhyFrame , &RecvPacket.FrameLength , RecvPacket.rxMetrics);
            if (CC2500_RX_OK == RxErr)
            {
                INT8U  StrTemp[4];
                
                WirelessControlWord.WirelessCommStatus = WIRELESS_COMM_STATUS_UHF_RECV_SUCCESS;
                
                //uart_write_line("\n\rLF Wake OK");
                //uart_write_line("\n\rCount:");
                //Hex2Str(&WirelessControlWord.RetryCnt,StrTemp,1);
                //uart_write_line(" 0x");
                //uart_write_line(StrTemp);
                
                
            }
            else if(CC2500_RX_NO_DATA == RxErr)
            {
                WirelessControlWord.WirelessCommStatus = WIRELESS_COMM_STATUS_UHF_RECVING;
                //uart_write_line("\n\rRx no data");
            }
            else
            {
                WirelessControlWord.WirelessCommStatus = WIRELESS_COMM_STATUS_UHF_RECV_ERR;
                //uart_write_line("\n\rLF Wake Fail");
            }
            break;
        case WIRELESS_COMM_STATUS_UHF_RECV_ERR:            
            
            StopTimer(WirelessControlWord.RecvOverTimerID);
            WirelessControlWord.RetryCnt++ ;
            WirelessControlWord.WirelessCommStatus = WIRELESS_COMM_STATUS_LF_TRANS;
            
            break;
        case WIRELESS_COMM_STATUS_UHF_RECV_SUCCESS:
            if (PACKET_TANS_OK == Packet2Frame(&RecvFrame , (PHY_FRAME*)(&RecvPacket)))
            {
                if (WIRELESSPROTOCOL_BROADCAST_CMD_COLLECT == RecvFrame.Command)
                {
                    INT8S Rssi = CC2500_CalculateRssi(RecvPacket.rxMetrics[CC2500_RX_METRICS_RSSI_OFS]);
                    
                    eSeal_New_eSealObj(RecvFrame.eSealID , RecvFrame.VendorID , RecvFrame.eSealStatus , Rssi);
                    //Reader collect operation here
                    WirelessControlWord.bUHFCommEstablished = TRUE;               

                    err = WIRELESS_COMM_LF_WAKE_UP_OK;
                    
                    //uart_write_line("\n\rCommand OK");
                }
                else
                {
                    StopTimer(WirelessControlWord.RecvOverTimerID);
                    WirelessControlWord.RetryCnt++ ;
                    WirelessControlWord.WirelessCommStatus = WIRELESS_COMM_STATUS_LF_TRANS;
                    
                    //uart_write_line("\n\rCommand Failed");
                }
                
                //uart_write_line("\n\rPacket2Frame OK");
            }
            else
            {
                StopTimer(WirelessControlWord.RecvOverTimerID);
                WirelessControlWord.RetryCnt++ ;
                WirelessControlWord.WirelessCommStatus = WIRELESS_COMM_STATUS_LF_TRANS;
                
                //uart_write_line("\n\rPacket2Frame Failed");
            }
            break;
        default:
            break;
        }
    } while ((FALSE == WirelessControlWord.bUHFCommEstablished)
             &&(WirelessControlWord.RetryCnt < WIRELESS_COMM_RETRY_TIMES));

    StopTimer(WirelessControlWord.RecvOverTimerID);
    WirelessControlWord.PreviousSentCmd = WIRELESSPROTOCOL_CMD_NULL;
    WirelessControlWord.RetryCnt = 0 ;
    WirelessControlWord.WirelessCommStatus = WIRELESS_COMM_STATUS_IDLE;

    return  err;
}


INT8U  WirelessCommUHF_Start(void)
{
    if (WIRELESS_COMM_STATUS_IDLE == WirelessControlWord.WirelessCommStatus)
    {
        WirelessControlWord.PreviousSentCmd = WIRELESSPROTOCOL_CMD_NULL;
        WirelessControlWord.RetryCnt = 0;
        WirelessControlWord.WirelessCommStatus = WIRELESS_COMM_STATUS_UHF_TRANS;
        WirelessControlWord.bResult = WIRELESS_COMM_FAILED;
        return TRUE;
    }
    else
        return FALSE;
}

INT8U  WirelessCommUHF_Trans(INT8U Trans_Cmd)
{
    if (WirelessControlWord.WirelessCommStatus == WIRELESS_COMM_STATUS_UHF_TRANS)
    {
        WirelessControlWord.PreviousSentCmd = Trans_Cmd;
        WirelessControlWord.WirelessCommStatus = WIRELESS_COMM_STATUS_UHF_RECVING;
        StartTimer(WirelessControlWord.RecvOverTimerID);

        if ((WirelessControlWord.RetryCnt) < WIRELESS_COMM_RETRY_TIMES)
        {
            return WIRELESS_COMM_RETRY;
        }
        else
            return WIRELESS_COMM_FAILED;
    }
    else
        return WIRELESS_COMM_TRYING;   
}


INT8U  WirelessCommUHF_Recv(INT8U Recv_Cmd)
{
    INT8U  err;
    err = WIRELESS_COMM_TRYING;
    INT8U  RxErr;
    switch (WirelessControlWord.WirelessCommStatus)
    {
    case WIRELESS_COMM_STATUS_UHF_RECVING:
        if (isTimeOver(WirelessControlWord.RecvOverTimerID))
        {
            StopTimer(WirelessControlWord.RecvOverTimerID);
            WirelessControlWord.WirelessCommStatus = WIRELESS_COMM_STATUS_UHF_TRANS;
            WirelessControlWord.RetryCnt++;
            break;
        }
        RxErr = CC2500_rxRecvPacket(RecvPacket.PhyFrame , &RecvPacket.FrameLength , RecvPacket.rxMetrics);
        if (CC2500_RX_OK == RxErr)
        {
            WirelessControlWord.WirelessCommStatus = WIRELESS_COMM_STATUS_UHF_RECV_SUCCESS;
        }
        else if(CC2500_RX_NO_DATA == RxErr)
        {
            WirelessControlWord.WirelessCommStatus = WIRELESS_COMM_STATUS_UHF_RECVING;
        }
        else
        {
            WirelessControlWord.WirelessCommStatus = WIRELESS_COMM_STATUS_UHF_RECV_ERR;
        }
        break;
    case WIRELESS_COMM_STATUS_UHF_RECV_ERR:
        StopTimer(WirelessControlWord.RecvOverTimerID);
        WirelessControlWord.WirelessCommStatus = WIRELESS_COMM_STATUS_UHF_TRANS;
        WirelessControlWord.RetryCnt++;
        break;
    case WIRELESS_COMM_STATUS_UHF_RECV_SUCCESS:
        if (PACKET_TANS_OK == Packet2Frame(&RecvFrame , (PHY_FRAME*)(&RecvPacket)))
        {
            if (Recv_Cmd == RecvFrame.Command)
            {
                INT8S Rssi = CC2500_CalculateRssi(RecvPacket.rxMetrics[CC2500_RX_METRICS_RSSI_OFS]);
                //eSeal_AddTable(RecvFrame.eSealID , RecvFrame.VendorID , RecvFrame.eSealStatus);
                if(eSeal_Check_eSealObjID(RecvFrame.eSealID , RecvFrame.VendorID))
                {
                    eSeal_Update_eSealObj(eSeal_Get_eSealObj(),RecvFrame.eSealStatus , Rssi);
                    err = WIRELESS_COMM_SUCCESS;
                }
                //eSealTable_Update_eSealObj(RecvFrame.eSealID , RecvFrame.VendorID , RecvFrame.eSealStatus , Rssi);          
                else
                   err = WIRELESS_COMM_STATUS_UHF_RECVING;
            }
            else
            {
                StopTimer(WirelessControlWord.RecvOverTimerID);
                WirelessControlWord.WirelessCommStatus = WIRELESS_COMM_STATUS_UHF_TRANS;
                WirelessControlWord.RetryCnt++;
            }
        }
        else
        {
            StopTimer(WirelessControlWord.RecvOverTimerID);
            WirelessControlWord.WirelessCommStatus = WIRELESS_COMM_STATUS_UHF_TRANS;
            WirelessControlWord.RetryCnt++;
        }
        break;
    default:
        break;
    }
    return (err);
}

void  WirelessCommUHF_End(INT8U CommStatus)
{
    switch (CommStatus)
    {
    case WIRELESS_COMM_SUCCESS:
        StopTimer(WirelessControlWord.RecvOverTimerID);
        WirelessControlWord.PreviousSentCmd = WIRELESSPROTOCOL_CMD_NULL;
        WirelessControlWord.RetryCnt = 0 ;
        WirelessControlWord.WirelessCommStatus = WIRELESS_COMM_STATUS_IDLE;
        WirelessControlWord.bResult = WIRELESS_COMM_SUCCESS;
        break;
    case WIRELESS_COMM_FAILED:
        StopTimer(WirelessControlWord.RecvOverTimerID);
        WirelessControlWord.PreviousSentCmd = WIRELESSPROTOCOL_CMD_NULL;
        WirelessControlWord.RetryCnt = 0 ;
        WirelessControlWord.WirelessCommStatus = WIRELESS_COMM_STATUS_IDLE;
        WirelessControlWord.bResult = WIRELESS_COMM_FAILED;
        break;
    case WIRELESS_COMM_RETRY:
    case WIRELESS_COMM_TRYING:
        break;
    default:
        break;
    }
}

INT8U  WirelessComm_IsCmdSuccess(void)
{
    if(WirelessControlWord.bResult == WIRELESS_COMM_SUCCESS)
        return TRUE;
    else
        return FALSE;
}